package me.jiatao.javestudy.generic;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by JiaTao on 2018/9/11.
 * Email: 535318720@qq.com
 * Version: 1.0
 * Description:
 */
public class GenericMain {
    public static void main(String[] args) {
//        System.out.println("------------上下限----------");
//        Integer integer = min(6, 4, 1, 7, 3, 6);
//        System.out.println(integer);

//        getPointIntegerType();

        Class clazzPointInteger = PointInteger.class;
        Type typePointInteger = clazzPointInteger.getGenericSuperclass();
        if (typePointInteger instanceof ParameterizedType) {
            System.out.println("typePointInteger instanceof ParameterizedType");
        }

        Class pointTypeVariableClass = PointTypeVariable.class;
        Type pointTypeVariableType = pointTypeVariableClass.getGenericSuperclass();
        if (pointTypeVariableType instanceof ParameterizedType){
            ParameterizedType  parameterizedType= (ParameterizedType) pointTypeVariableType;

            Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                if (actualTypeArgument instanceof TypeVariable){
                    TypeVariable typeVariable= (TypeVariable) actualTypeArgument;
                    System.out.println("actualTypeArgument instanceof TypeVariable");
                    String name=typeVariable.getName();
                    System.out.println("typeVariable.getName-->"+name);

                    Type[] typebounds = typeVariable.getBounds();
                    for (Type bound:typebounds){
                        Class<?> boundClass = (Class)bound;
                        //如果不写，则默认输出Object，如果写了，则输出对应的
                       System.out.println("bound为：" + boundClass.getName());
                    }
                }

                if (actualTypeArgument instanceof  Class){
                    Class parameterArgClass = (Class) actualTypeArgument;
                   System.out.println("此接口的填充类型为：" + parameterArgClass.getName());
                }
            }
        }

    }


    public static void getPointIntegerType() {
        Class clazz = PointInteger.class;
        Type type = clazz.getGenericSuperclass();
        if (type instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) type;
            //返回表示此类型实际类型参数的 Type 对象的数组
            Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                Class parameterArgClass = (Class) actualTypeArgument;
                System.out.println("填充类型为：" + parameterArgClass.getName());
            }

            //返回 Type 对象，表示声明此类型的类或接口。
            Type type1 = parameterizedType.getRawType();
            Class class22 = (Class) type1;
            System.out.println("PointInteger的父类类型为：" + class22.getName());
        }
    }


    /**
     * 泛型类
     */
    public static void classType() {
//        PointClass<Integer> point = new PointClass<>();
//        point.setX(100);
//        point.setY(200);
//        System.out.println(point.toString());

    }

    /**
     * 泛型方法
     */
    public static void function() {
        StaticFanction.StaticMethod("StaticMethod");
        StaticFanction.<String>StaticMethod("StaticMethod2");

        StaticFanction staticFanction = new StaticFanction();
        staticFanction.OtherMethod("OtherMethod");
        staticFanction.<String>OtherMethod("OtherMethod2");


        List list = StaticFanction.returnArray(1, 2, 3, 4, "AAA", 5, 6);
        for (Object o : list) {
            System.out.print(o);
        }
        System.out.println();
        List list2 = StaticFanction.<Integer>returnArray(1, 2, 3, 4, 5, 6);
        for (Object o : list2) {
            System.out.print(o);
        }
    }

    /**
     * 上下限
     *
     * @param a
     * @param <T>
     * @return
     */
    public static <T extends Comparable> T min(T... a) {
        T smallest = a[0];
        for (T item : a) {
            if (smallest.compareTo(item) == 1) {
                smallest = item;
            }
        }
        return smallest;
    }

    /**
     * ? extends 上限
     */
    public static void extendsFunc() {
        //        PointClass<?> point;
//        point = new PointClass<Integer>(3, 3);
//        point = new PointClass<Float>(4.3f, 4.3f);
//        point = new PointClass<Double>(4.3d, 4.90d);
//        point = new PointClass<Long>(12l, 23l);
//        point = new PointClass<String>("111", "222");

//        PointClass<? extends Number> point2;
//        point2 = new PointClass<Integer>(3, 3);
//        point2 = new PointClass<Float>(4.3f, 4.3f);
//        point2 = new PointClass<Double>(4.3d, 4.90d);
//        point2 = new PointClass<Long>(12l, 23l);
//
//        Number number = point2.getX();
//        System.out.println(number.intValue());
////        point2.setX(new Integer(1));//编译出错
    }

    /**
     * ? super 下限
     */
    public static void superFunc() {
        List<? super Person.Manager> list;
        list = new ArrayList<Person.Employee>();
//存
//        list.add(new Person.Employee()); //编译错误
        list.add(new Person.Manager());
        list.add(new Person.CEO());
//取
//        Person.Manager manager = list.get(1);
        Object object = list.get(0);
    }


}